# CurrentThreadConnectionProvider.java

    package org.codefilarete.stalactite.sql;

    import javax.sql.DataSource;
    import java.sql.Connection;
    import java.sql.SQLException;

    import org.codefilarete.tool.sql.ConnectionWrapper;

    /**
     * Implementation which {@link #giveConnection()} gives the current {@link Connection} as a Thread point of view. It may be detached from it
     * thanks to {@link #releaseConnection()}.
     * Connections source is the underlying {@link DataSource} given at construction time.
     * Connections are set in transactional mode through {@link Connection#setAutoCommit(boolean)} with false as parameter.
     *
     * @author Guillaume Mary
     */
    public class CurrentThreadConnectionProvider implements ConnectionProvider {

    	private final ConnectionProvider dataSource;

    	private final ThreadLocal<Connection> currentConnection = new ThreadLocal<>();

    	public CurrentThreadConnectionProvider(DataSource dataSource) {
    		this(new DataSourceConnectionProvider(dataSource));
    	}

    	public CurrentThreadConnectionProvider(ConnectionProvider dataSource) {
    		this.dataSource = dataSource;
    	}

    	/**
    	 * Implemented to provide current {@link Thread} {@link Connection}. If one doesn't exist then it is filled and will be provided on next calls.
    	 *
    	 * @return current Thread {@link Connection}
    	 * @see #releaseConnection()
    	 * @see #fillCurrentConnection()
    	 */
    	@Override
    	public Connection giveConnection() {
    		Connection connection = this.currentConnection.get();
    		try {
    			if (connection == null) {
    				return fillCurrentConnection();
    			} else if (connection.isClosed()) {
    				this.currentConnection.remove();	// closed connection has no interest
    				return fillCurrentConnection();
    			} else {
    				return connection;
    			}
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}
    	}

    	/**
    	 * Attaches a {@link Connection} to current {@link Thread}
    	 * {@link Connection} is set auto-commit to false for enabling transaction mode because it better suits usual ORM usage.
    	 *
    	 * @return the attached {@link Connection}
    	 */
    	public Connection fillCurrentConnection() {
    		try {
    			Connection connection = new CurrentThreadDetacherConnection(this.dataSource.giveConnection());
    			// Connection is set in transactional mode because it better suits ORM usage even if it doesn't manage transactions itself
    			connection.setAutoCommit(false);
    			this.currentConnection.set(connection);
    			return connection;
    		} catch (SQLException e) {
    			throw new RuntimeException(e);
    		}
    	}

    	/**
    	 * Detaches current {@link Thread} from its {@link Connection}
    	 */
    	public void releaseConnection() {
    		this.currentConnection.remove();
    	}

    	/**
    	 * Connection that wraps another one and will release it from current Thread on close.
    	 * made to avoid that Threads keep a reference for duration between close of a connection and opening of a new one
    	 */
    	private class CurrentThreadDetacherConnection extends ConnectionWrapper {

    		private CurrentThreadDetacherConnection(Connection connection) {
    			super(connection);
    		}

    		@Override
    		public void close() throws SQLException {
    			releaseConnection();
    			super.close();
    		}
    	}
    }